﻿<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="../helpproject.xsl" ?>
<topic template="Default" lasteditedby="Geert" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../helpproject.xsd">
  <title translate="true">Memento</title>
  <keywords>
    <keyword translate="true">IMementoService</keyword>
    <keyword translate="true">Memento</keyword>
    <keyword translate="true">MementoService</keyword>
    <keyword translate="true">Redo</keyword>
    <keyword translate="true">Undo</keyword>
  </keywords>
  <body>
    <header>
      <para styleclass="Heading1"><text styleclass="Heading1" translate="true">Memento</text></para>
    </header>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">Lots of real world applications need to implement undo/redo. However, most applications written in MVVM lack this feature because it is very hard to implement. Luckily, Catel solves this issue by introducing the </text><link displaytype="text" defaultstyle="true" type="topiclink" href="T_Catel_Memento_IMementoService" styleclass="Normal" translate="true">IMementoService</link><text styleclass="Normal" translate="true">. The </text><link displaytype="text" defaultstyle="true" type="topiclink" href="T_Catel_Memento_IMementoService" styleclass="Normal" translate="true">IMementoService</link><text styleclass="Normal" translate="true"> is a service that allows a developer to register custom actions that should be undone. A few actions you can think of:</text></para>
    <list id="2" type="ul" listtype="bullet" formatstring="·" format-charset="SYMBOL_CHARSET" levelreset="true" legalstyle="false" startfrom="1" styleclass="Normal (list)" style="font-family:Symbol; font-size:10pt; color:#000000;">
      <li styleclass="Normal (list)"><text styleclass="Normal (list)" translate="true">Property change of a model</text></li>
      <li styleclass="Normal (list)"><text styleclass="Normal (list)" translate="true">Item is added or removed to/from a collection</text></li>
      <li styleclass="Normal (list)"><text styleclass="Normal (list)" translate="true">A method is executed</text></li>
    </list>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">One way to introduce the memento pattern is by creating a copy of the whole memory at each step (yes, some people actually do this), but in Catel it is done a bit smarter. For each possible action type, there is an implementation of the </text><link displaytype="text" defaultstyle="true" type="topiclink" href="T_Catel_Memento_UndoBase" styleclass="Normal" translate="true">UndoBase</link><text styleclass="Normal" translate="true">. This way, each action will know by itself how to undo or redo. Catel offers the following default implementations:</text></para>
    <list id="3" type="ul" listtype="bullet" formatstring="·" format-charset="SYMBOL_CHARSET" levelreset="true" legalstyle="false" startfrom="1" styleclass="Normal (list)" style="font-family:Symbol; font-size:10pt; color:#000000;">
      <li styleclass="Normal (list)"><link displaytype="text" defaultstyle="true" type="topiclink" href="T_Catel_Memento_PropertyChangeUndo" styleclass="Normal (list)" translate="true">PropertyChangeUndo</link></li>
      <li styleclass="Normal (list)"><link displaytype="text" defaultstyle="true" type="topiclink" href="T_Catel_Memento_CollectionChangeUndo" styleclass="Normal (list)" translate="true">CollectionChangeUndo</link></li>
      <li styleclass="Normal (list)"><link displaytype="text" defaultstyle="true" type="topiclink" href="T_Catel_Memento_ActionUndo" styleclass="Normal (list)" translate="true">ActionUndo</link></li>
    </list>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">If there are more actions supported, it is possible to write a custom </text><link displaytype="text" defaultstyle="true" type="topiclink" href="T_Catel_Memento_UndoBase" styleclass="Normal" translate="true">UndoBase</link><text styleclass="Normal" translate="true"> implementation and add the specific action to the </text><link displaytype="text" defaultstyle="true" type="topiclink" href="T_Catel_Memento_IMementoService" styleclass="Normal" translate="true">IMementoService</link><text styleclass="Normal" translate="true">. It will automatically be added to the undo/redo action stack.</text></para>
    <para styleclass="Heading1"><text styleclass="Heading1" translate="true">Undo and redo support</text></para>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">The </text><link displaytype="text" defaultstyle="true" type="topiclink" href="T_Catel_Memento_IMementoService" styleclass="Normal" translate="true">IMementoService</link><text styleclass="Normal" translate="true"> supports both undo and redo actions. This means that an action that is undo-ed by a call to the </text><link displaytype="text" defaultstyle="true" type="topiclink" href="M_Catel_Memento_IMementoService_Undo" styleclass="Normal" translate="true">Undo</link><text styleclass="Normal" translate="true"> method, it is automatically added to the redo stack when redo is supported.</text></para>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">To undo an action, use the code below:</text></para>
    <para styleclass="Code Example"><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true">var</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#ffffff;" translate="true"> </text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true">mementoService</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#ffffff;" translate="true"> </text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true">=</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#ffffff;" translate="true"> </text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true">ServiceLocator.Instance.ResolveType&lt;IMementoService&gt;();</text><br/><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true">mementoService.Undo();</text></para>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">It is possible to check whether it is possible to undo actions by using the </text><link displaytype="text" defaultstyle="true" type="topiclink" href="P_Catel_Memento_IMementoService_CanUndo" styleclass="Normal" translate="true">CanUndo</link><text styleclass="Normal" translate="true"> property. This check is not required since the </text><link displaytype="text" defaultstyle="true" type="topiclink" href="M_Catel_Memento_IMementoSupport_Undo" styleclass="Normal" translate="true">Undo</link><text styleclass="Normal" translate="true"> method will also check this internally.</text></para>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">To redo an action, use the code below:</text></para>
    <para styleclass="Code Example"><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true">var</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#ffffff;" translate="true"> </text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true">mementoService</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#ffffff;" translate="true"> </text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true">=</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#ffffff;" translate="true"> </text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true">ServiceLocator.Instance.ResolveType&lt;IMementoService&gt;();</text><br/><text styleclass="Code Example" style="font-weight:normal; font-style:normal; text-decoration:none; color:#000000;" translate="true">mementoService.Redo();</text></para>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">It is possible to check whether it is possible to redo actions by using the </text><link displaytype="text" defaultstyle="true" type="topiclink" href="P_Catel_Memento_IMementoService_CanRedo" styleclass="Normal" translate="true">CanRedo</link><text styleclass="Normal" translate="true"> property. This check is not required since the </text><link displaytype="text" defaultstyle="true" type="topiclink" href="M_Catel_Memento_IMementoSupport_Redo" styleclass="Normal" translate="true">Redo</link><text styleclass="Normal" translate="true"> method will also check this internally.</text></para>
    <para styleclass="Heading1"><text styleclass="Heading1" translate="true">Ignoring support for memento</text></para>
    <para styleclass="Normal"><text styleclass="Normal" translate="true">Ignoring specific properties or methods for the </text><link displaytype="text" defaultstyle="true" type="topiclink" href="T_Catel_Memento_IMementoService" styleclass="Normal" translate="true">IMementoService</link><text styleclass="Normal" translate="true"> is very easy. Just decorate them with the </text><link displaytype="text" defaultstyle="true" type="topiclink" href="T_Catel_Memento_IgnoreMementoSupportAttribute" styleclass="Normal" translate="true">IgnoreMementoSupportAttribute</link><text styleclass="Normal" translate="true"> as shown below:</text></para>
    <para styleclass="Code Example"><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">[IgnoreMementoSupport]</text><br/><text styleclass="Code Example" style="font-weight:bold; font-style:normal; color:#000000;" translate="true">public</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true"> </text><text styleclass="Code Example" style="font-weight:bold; font-style:normal; color:#000000;" translate="true">string</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true"> </text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">IgnoredProperty</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true"> </text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">{</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true"> </text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">get;</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true"> </text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">set;</text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#ffffff;" translate="true"> </text><text styleclass="Code Example" style="font-weight:normal; font-style:normal; color:#000000;" translate="true">}</text></para>
  </body>
</topic>
